package limiter;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import com.google.common.util.concurrent.AtomicDouble;

/**
 * 
 * @author STAR
 * TODO
 * 限流器
 */
public class MyRateLimiter{

	static ReentrantLock lock = new ReentrantLock();
	//	@Min(1)
	/**
	 * 缓存桶
	 */
	private static double replenishRate = 1;

	//	@Min(1)
	/**
	 * 流速
	 */
	private static double burstCapacity = 20;

	/**
	 * 总容积
	 */
	private static double totalRate = replenishRate+burstCapacity;
	
	private static AtomicDouble currentCup = new AtomicDouble(totalRate);

	private static long reflushTime = 10L;

	private static double onpice = burstCapacity*reflushTime/1000;
	
	public static boolean isAllowed(String token) {

		if(currentCup.get()<1) {
			return false;
		} else {
			currentCup.set(currentCup.doubleValue()-1.0);
		}

		return true;

	}

	public static void reflush() {
		if(currentCup.get()<burstCapacity) {
			if(currentCup.addAndGet(onpice)>totalRate) {
				currentCup.set(totalRate);
			}
//			System.out.println(currentCup.get());
		}
	}

	public static void main(String[] args) {
		
		System.out.println((burstCapacity*reflushTime)/1000);
		long time0 = System.currentTimeMillis();
		
//		for(int i=0;i<50;i++) {
//			MyRateLimiter.lock.lock();
//			MyRateLimiter.isAllowed("");
////			System.out.println(MyRateLimiter.isAllowed(""));
////			if(allowed) {
////				System.out.println("return"+allowed);
////			}else {
////				System.out.println(".");
////			}
//
//			MyRateLimiter.lock.unlock();
////			try {
////				Thread.sleep(1000L);
////			} catch (InterruptedException e) {
////				// TODO Auto-generated catch block
////				e.printStackTrace();
////			}
//		}
		
//		long time1 = System.currentTimeMillis();
//		System.out.println(time1-time0);
		
		

		List<Thread> list = new ArrayList<Thread>();
		
//		new Thread() {
//
//			@Override
//			public void run() {
//				for(;;) {
//					MyRateLimiter.reflush();
//					try {
//						Thread.sleep(MyRateLimiter.reflushTime);
//					} catch (InterruptedException e) {
//						// TODO Auto-generated catch block
//						e.printStackTrace();
//					}
//				}
//			
//			}
//			
//		}.start();
		
		for(int i=0;i<15;i++) {

			list.add(new Thread() {

				@Override
				public void run() {
					for(;;) {
						MyRateLimiter.lock.lock();
						boolean allowed = MyRateLimiter.isAllowed("");
						if(allowed) {
							System.out.println("return"+allowed);
						}else {
							System.out.println(".");
						}

						MyRateLimiter.lock.unlock();
						try {
							Thread.sleep(1000L);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
				}

			});
		}
		for(int j=0;j<list.size();j++) {
			list.get(j).start();
		}
	}
	static {
		new Thread() {
			@Override
			public void run() {
				for(;;) {
					MyRateLimiter.reflush();
					try {
						Thread.sleep(MyRateLimiter.reflushTime);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
		}.start();
	}

}
